#pragma once
#include "stdafx.h"
#include "Utils.h"
#include "Wx_GlobalData.h"
#include "Wx_AddrOffest.h"
#include "Wx_Utils.h"
#include "include/rapidjson/writer.h"
#include "include/rapidjson/stringbuffer.h"

using namespace rapidjson;

static DWORD databaseHandleAddr;
static DWORD databaseHandleNextAddr;
static DWORD databaseHandleParam;


void _databaseWorkFunc(DWORD key, DWORD value) {

	DWORD len = wcslen((TCHAR*)key) * 2 + 2;
	TCHAR* tempKey = new TCHAR[len];
	memcpy((CHAR*)tempKey, (CHAR*)key, len);
	databaseMap[tempKey] = value;

	//PrintFunAddr(databaseMap[tempKey]);
}

void __declspec(naked) _databaseWork() {
	__asm {
		pushad
		pushfd
		push[ebp - 0x14]
		push [edi]
		call _databaseWorkFunc
		add esp, 0x8
		popfd
		popad
		mov esi, dword ptr ss : [ebp - 0x14]
		add esp, 0x8
		jmp databaseHandleNextAddr
	}
}

bool Wx_GetDatabaseHandle() {

	PrintFunAddr((DWORD)Wx_GetDatabaseHandle);

	databaseHandleAddr = (DWORD)hWeChatWin + ADDR_GETDATABASEHANDLE_ADDR_OFFEST;
	databaseHandleNextAddr = (DWORD)hWeChatWin + ADDR_GETDATABASEHANDLE_NEXT_OFFEST;
	databaseHandleParam = (DWORD)hWeChatWin + ADDR_GETDATABASEHANDLE_PARAM_OFFEST;


	DWORD addrHookMachineCode = (DWORD)_databaseWork - databaseHandleAddr - 5;

	BYTE machineCode[6];
	machineCode[0] = 0xe9;
	CHAR* addrTempHookMachineCode = (CHAR*)&addrHookMachineCode;
	machineCode[1] = *(addrTempHookMachineCode + 0);
	machineCode[2] = *(addrTempHookMachineCode + 1);
	machineCode[3] = *(addrTempHookMachineCode + 2);
	machineCode[4] = *(addrTempHookMachineCode + 3);
	machineCode[5] = 0x90;

	BOOL flag = WriteProcessMemory((HANDLE)-1, (LPVOID) * &databaseHandleAddr, machineCode, sizeof(machineCode), NULL);
	if (flag > 0) {
		return 1;
	}
	else {
		return 0;
	}

}



int databaseExecCallback(void* param, int nColumn, char** colValue, char** colName)
{
	
	Writer<StringBuffer, UTF16<>>* writer = (Writer<StringBuffer, UTF16<>>*)param;
	
	writer->StartObject();
	writer->Key(L"colNum");
	writer->Int(nColumn);

	for (int i = 0; i < nColumn; i++)
	{
		
		DWORD buffSize = MultiByteToWideChar(CP_ACP, 0, *(colName + i), -1, 0, 0);
		TCHAR* buff = new TCHAR[buffSize];
		MultiByteToWideChar(CP_ACP, 0, *(colName + i), -1, buff, buffSize);
		writer->Key(buff);

		delete[] buff;
		buff = NULL;
		buffSize = 0;

		buffSize = MultiByteToWideChar(CP_ACP, 0, *(colValue + i), -1, 0, 0);
		buff = new TCHAR[buffSize];
		MultiByteToWideChar(CP_ACP, 0, *(colValue + i), -1, buff, buffSize);
		writer->String(buff);
		
		delete[] buff;
		buff = NULL;

	}

	writer->EndObject();

	return 0;
}

void Wx_DatabaseExec(TCHAR* dbName, CHAR* sql, Wx_jsonBuff* jb) {

	PrintFunAddr((DWORD)Wx_DatabaseExec);

	if (databaseMap.count(dbName) > 0) {

		DWORD execCall = (DWORD)hWeChatWin + ADDR_DATABASEEXEC_CALL_OFFEST;
		DWORD db = databaseMap[dbName];

		StringBuffer s;
		Writer<StringBuffer, UTF16<>>* writer = new Writer<StringBuffer, UTF16<>>(s);

		writer->StartObject();
		writer->Key(L"type");
		writer->String(L"Wx_DatabaseExec");
		writer->Key(L"status");
		writer->String(L"success");
		writer->Key(L"wxid");
		writer->String(wxOwnInfo.wxId);
		writer->Key(L"content");
		writer->StartObject();
		writer->Key(L"list");
		writer->StartArray();

		__asm {
			push 0
			push writer
			push databaseExecCallback
			push sql
			push db
			call[execCall]
			add esp, 0x14
		}


		writer->EndArray();
		writer->EndObject();
		writer->EndObject();

		jb->str = std::string(s.GetString());
		jb->len = s.GetSize();
		//sctSocket.wxSend((CHAR*)s.GetString(), s.GetSize());
		delete writer;
	}
	else {

		WxErrDataJsonBuild* json = new WxErrDataJsonBuild((TCHAR*)L"Wx_DatabaseExec", (TCHAR*)L"not found db");
		jb->str = std::string(json->s.GetString());
		jb->len = json->s.GetSize();
		//sctSocket.wxSend((CHAR*)json->s.GetString(), json->s.GetSize());
		delete json;
		json = NULL;
	}


}